<?php

/**
 * micro templating engine.
 * No control blocks, only feeds variables blocks
 */
class uTpl {

    /**
     * constructor
     * @param string $tpl template string
     *
     */
    function uTpl($tpl='') {
        $this->tpl=&$tpl;
    }

    /**
     * feeds template with data and return rednered result
     * @access public
     * @param array $data data to inject
     * @return string
     */
    function render($data=array()) {
        return $this->_feed($this->tpl,$data);
    }

    /**
     * feeds template with data
     * @access protected
     * @param string $tpl
     * @param array $data
     */
    function _feed($tpl,$data) {
        // parsing regular expression
		static $regex='\{([^{}]*)\{([a-zA-Z][a-zA-Z0-9_\.-]*)\}([^{}]*)\}';
        // loop counter
        $n=0;
		while (ereg($regex,$tpl,$found)) {
			// avoiding infinite loop
			$n++; if ($n>50) break;
            // print_r($found);
			// storing optional block before var
			$before=$found[1];
            // var name
			$key=$found[2];
			// storing optional block after var
			$after=$found[3];
			// evaluating var
			if (isset($data[$key])
			and $this->_bool($data[$key])) {
                // buidlign replacement block
				$replace=$before.$this->_value($data[$key]).$after;
			} else {
				// not provided or null value
				$replace='';
			}
			// replacing blocks
			// escaping regex special chars
			$before=str_replace('(','\(',$before);
			$before=str_replace(')','\)',$before);
			$after=str_replace('(','\(',$after);
			$after=str_replace(')','\)',$after);
			// replacing regex
			$ereg2='\{'.$before.'\{'.$key.'\}'.$after.'\}';
			$tpl=ereg_replace($ereg2,$replace,$tpl);
		}
        return $tpl;
    }

    /**
     * evaluates var to booleans for conditonal blocks
     */
    function _bool($var) {
        return $var?true:false;
    }

    /**
     * converts vars to strings
     * @access protected
     * @param mixed var
     * @return string
     */
    function _value($var) {
        switch (true) {
            case is_null($var):
                return $this->_nullValue();
            case is_bool($var):
                return $this->_boolValue($var);
            case is_object($var):
                $method='_'.get_class($var).'Value';
                if (method_exists($this,$method))
                    return $this->$method($var);
                return $this->_objectValue($var);
            default:
                return strval($var);
        }
    }

    function _strValue($var) {
        return $var;
    }

    function _nullValue() {
        return '';
    }

    function _boolValue($var) {
        return '';
    }

    function _objectValue($var) {
        return strval($var);
    }

}
